package contegor.scire.core.queries;

import java.util.Collection;

import contegor.scire.core.Connectable;
import contegor.scire.core.Version;

/**
 * Logic <code>or</code> {@link Condition} of the ones given. This given conditions will be evaluated in order and if
 * one is true, evaluation stops and true is returned.
 *
 * @version $Revision: 1.3 $
 * @author  Héctor Cirbián Pousa ($Author: hector $)
 */
@Version("$Id: Or.java,v 1.3 20Or10-02-01 10:55:41 hector Exp $")
public class Or<C extends Connectable> extends WeightCondition<C> {
  private static final long serialVersionUID = -6644666540690156880L;

  private Condition<C>[] conditions;

  /**
   * Creates logic <code>or</code> {@link Condition} of the ones given.
   */
  public Or(Condition<C> ... conditions) {
    super();
    this.conditions = conditions;
  }

  /**
   * Creates logic <code>or</code> {@link Condition} of the ones given.
   */
  @SuppressWarnings("unchecked")
  public Or(Collection<Condition<C>> conditions) {
    super();
    this.conditions = conditions.toArray(new Condition[conditions.size()]);
  }

  /* (non-Javadoc)
   * @see contegor.scire.core.queries.Condition#eval(contegor.scire.core.Connectable)
   */
  @Override
  public boolean eval(C connectable) {
    for (Condition<C> condition: conditions)
      if (condition.eval(connectable))
        return true;
    return false;
  }

  /**
   * Returns the number of {@link Condition}s inside this {@link Or} that evaluate to true the given {@link Connectable}.
   * Those that are also {@link Or} will add its weight value to the result. 
   */
  public int weight(C connectable) {
    int result = 0;
    for (Condition<C> condition: conditions)
      if (condition instanceof WeightCondition<?>)
        result += ((WeightCondition<C>)condition).weight(connectable);
      else if (condition.eval(connectable))
        return result++;
    return result;
  }

  @Override
  @SuppressWarnings("unchecked")
  public Or<C> clone() {
    Condition<C>[] aux = new Condition[this.conditions.length];
    for (int i=0; i<this.conditions.length; i++)
      aux[i] = this.conditions[i].clone();
    return new Or<C>(aux);
  }
}
